﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Configuration;
using System.Windows.Forms;
using System.Xml;
using SdmxMl.Common;
using SdmxMl.Structure;
using SdmxMl.GenericMetadata;
using SdmxMl.Helper;
using SdmxMl.Msg;
using SdmxMl.Panels;
using SdmxMl.UC;
using SdmxMl.Excel;
using SdmxMl.Data;
using SdmxMl.Multiplexor;

namespace SdmxMl.Manager
{
    public class CategoryEntryManager
    {
        #region Internal members

        private static string CategoryRootFullId;
        private static string StatActivitiesFullId;
        private DateTime dtCreated;

        /// <summary>Entry point in menu for Categories entries points</summary>
        private ToolStripMenuItem menuCategoryRoot;
        /// <summary>List of menu items to support</summary>
        private CodeListType cltCat;
        /// <summary>SFSO Activities with annotation for binding</summary>
        private CategorySchemeType catActivity;

        private Dictionary<string, string> dicoCatFullid;

        #endregion

        #region C'tor

        public CategoryEntryManager(ToolStripMenuItem tsm)
        {
            menuCategoryRoot = tsm;
            dicoCatFullid = new Dictionary<string, string>();
            dtCreated = DateTime.Now;

            // Fetch information in Admin registry
            if (string.IsNullOrEmpty(CategoryRootFullId) == false)
            {
                try
                {
                    SmManager sm = new SmManager();
                    ArtefactRefTyped art = new ArtefactRefTyped(SdmxArtefactType.CodeLists, CategoryRootFullId);
                    cltCat = sm.GetArtefact(SdmxArtefactType.CodeLists, art, true) as CodeListType;

                    // Crreate menu items under root
                    if (cltCat != null)
                    {
                        foreach (CodeType c in cltCat.CodeList)
                        {
                            // One menuItem per code entry, common entry method, tag is code ID
                            ToolStripMenuItem m = new ToolStripMenuItem();

                            m.Text = c.Name.GetForLanguage("en");
                            m.Tag = c.Id;

                            // attach to parent
                            menuCategoryRoot.DropDownItems.Add(m);

                            // create click event
                            m.Click += new EventHandler(Category_Click);
                        }

                        // Activities
                        PrepareActivities();
                    }
                    else
                        menuCategoryRoot.Enabled = false;
                }
                catch 
                {
                    menuCategoryRoot.Enabled = false;
                    throw;
                }
            }
            else
                menuCategoryRoot.Enabled = false;
        }

        private void PrepareActivities()
        {
            // Statistical Activities
            if (string.IsNullOrEmpty(StatActivitiesFullId) == false)
            {
                SmManager sm = new SmManager();
                ArtefactRefTyped art = new ArtefactRefTyped(SdmxArtefactType.CategorySchemes, StatActivitiesFullId);
                catActivity = sm.GetArtefact(art.Type, art, true) as CategorySchemeType;
                if (catActivity == null)
                    throw new ApplicationException("Unable to load Statistical activities: " + StatActivitiesFullId);

                // Make a list of fullId REFERED in top hierarchy level
                dicoCatFullid.Clear();
                foreach (Category cat in catActivity.CategoryList)
                {
                    foreach (Annotation ann in cat.AnnotationList)
                    {
                        if (ann.Url != null)
                        {
                            UrnParser p = new UrnParser(ann.Url.ToString());
                            if (p.IsSupported && dicoCatFullid.ContainsKey(ann.Type) == false)
                                dicoCatFullid.Add(ann.Type, p.FullIdent);
                        }
                    }
                }
            }
        }

        #endregion

        #region Static C'tor

        static CategoryEntryManager()
        {
            if (ConfigurationManager.AppSettings["CategoryRootFullId"] != null)
                CategoryRootFullId = ConfigurationManager.AppSettings["CategoryRootFullId"].ToString().Trim();
            else
                CategoryRootFullId = string.Empty;

            if (ConfigurationManager.AppSettings["StatActivitiesFullId"] != null)
                StatActivitiesFullId = ConfigurationManager.AppSettings["StatActivitiesFullId"].ToString().Trim();
            else
                StatActivitiesFullId = string.Empty;

        }

        #endregion

        #region menu Item event

        void Category_Click(object sender, EventArgs e)
        {
            try
            {

                // Do we need to reload activities
                if (string.IsNullOrEmpty(StatActivitiesFullId) == false)
                {
                    if (Mux.Instance.IsArtefactUpdated(SdmxArtefactType.CategorySchemes.ToString(), StatActivitiesFullId, dtCreated))
                    {
                        PrepareActivities();
                        dtCreated = DateTime.Now;
                    }
                }

                ToolStripMenuItem tm = sender as ToolStripMenuItem;
                if (tm != null && tm.Tag != null)
                {
                    ISdmxHierarchyListItem item = cltCat.CodeList.LocateItem(tm.Tag.ToString());
                    if (item != null)
                    {
                        CodeType c = item as CodeType;
                        if (string.IsNullOrEmpty(c.Uri) == false)
                        {
                            //Request load
                            UrnParser p = new UrnParser(c.Uri);

                            if (dicoCatFullid.ContainsKey(c.Id))
                            {
                                // load requested, Add activities
                                SmManager sm = new SmManager();
                                ArtefactRefTyped art = new ArtefactRefTyped(p.ArType, p.FullIdent);
                                CategorySchemeType cst = sm.GetArtefact(art.Type, art, true) as CategorySchemeType;
                                cst.IsFinal = true;

                                // pour chaque activité (root level) get matching annotation
                                foreach (Category cat in catActivity.CategoryList)
                                {
                                    Annotation ann = cat.AnnotationList.GetAnnotationType(c.Id);
                                    if (ann != null && ann.Url != null)
                                    {
                                        UrnParser pActivity = new UrnParser(ann.Url.ToString());
                                        if (pActivity.IsSupported)
                                        {
                                            Category catGroup = cst.CategoryList.LocateItemFromFullId(pActivity.SubTypeId, cst.CategoryList) as Category;
                                            if (catGroup != null)
                                            {
                                                catGroup.CategoryList.Add(cat);
                                            }
                                        }
                                    }
                                }

                                // TODO check if already in memory
                                RemoveIfInMemory(art);

                                // Now transmit to tree
                                string fileName = string.Empty;

                                // Use temp dir 
                                fileName = System.IO.Path.GetTempPath() + "SMS_SAE_temp.xml";
                                XmlDocument xDoc = sm.GetAsDocument();
                                xDoc.Save(fileName);
                                ReferenceManager.TreeMgr.LoadSdmxArtefact(fileName, true, null);
                            }
                            else
                            {
                                ArtefactRefTyped art = new ArtefactRefTyped(p.ArType, p.FullIdent);
                                RemoveIfInMemory(art);
                                NavigationManager.NavigateWithRegistry(p.ArType, p.FullIdent, true, p);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error");
            }
        }


        private void RemoveIfInMemory(ArtefactRefTyped art)
        {
            // If artefact already in memory remove it
            Artefact aTarget = ReferenceManager.LocateArtefact(art.Type, art);
            if (aTarget != null)
            {
                TreeNode targetNode = null;
                TreeView tv = ReferenceManager.TreeSdmx;
                if (tv != null)
                {
                    TreeHelper.LocateObject(tv, aTarget, ref targetNode);
                    if (targetNode != null)
                    {
                        ArtefactManager arm = targetNode.Parent.Tag as ArtefactManager;
                        if (arm != null)
                        {
                            targetNode.Parent.Nodes.Remove(targetNode);
                            arm.ArtefactList.Remove(aTarget);
                        }
                    }
                }
            }

        }

        #endregion
    }
}
